import { createUpdateId, EChart, TEChartDatasetInfo, TEChartInfo, TEChartOptions, TEchartUpdateInfo, TUpdateInfoValueType } from "@/models/reactiveComponent"
import { TDbServices } from "@/services/dbServices"
import { set, groupBy } from "lodash-es";
import { TEchartEventParams, TEchartInstance, TServices } from "./types";

export function clearAllPybiSeries(options: TEChartOptions) {
    if (!Array.isArray(options.series)) {
        options.series = [options.series]
    }

    options.series = (options.series as {}[]).filter(s => !('pybiFlag' in s))
}

export type TDbQuery = ReturnType<TDbServices['queryAll']>


const universalTransition = {
    "enabled": true,
    "divideShape": "clone"
}

export function normalOptionsHandler(
    info: TEChartDatasetInfo,
    options: TEChartOptions,
    query: TDbQuery,
    encodeFn: (fields: string[], currentIdx: number) => {},
    postOptionsHandler: (options: TEChartOptions) => void,
) {

    set(options, `${info.path}.source`, Array.from(query.toRowsArrayHasHeader()))

    if (query.rows.length > 0) {

        // append series
        for (let index = 1; index < query.fields.length; index++) {


            const encode = encodeFn(query.fields, index)
            options.series.push({ id: index, ...info.seriesConfig, universalTransition: true, name: query.fields[index], encode, pybiFlag: null })

        }

        if (options.series.length === 1) {
            // options.series[0]['name'] = query.fields[0]
        }

        postOptionsHandler(options)
    }
}


const valueMap = new Map<TEchartUpdateInfo['valueType'], string>([
    ['x', 'name'],
    ['value', 'name'],
    ['y', 'value'],
])


export function getEChartEventParamsValue(params: TEchartEventParams,
    valueType: TUpdateInfoValueType) {
    const propName = valueMap.get(valueType)!
    return params[propName]
}

export function addFilterToDataset(
    expression: string,
    model: EChart,
    infoIndex: number,
    services: TServices,
    datasetName: string) {

    const chartOptId = createUpdateId(model, infoIndex);
    services.dataset.addFilter(chartOptId, datasetName, expression);
}


export type TCatDimFieldCache = ReturnType<typeof createCatDimFieldCache>

export function createCatDimFieldCache() {

    return function () {
        let catDimField = ''

        const value = () => catDimField

        function setItemGroupField(value: string) {
            catDimField = value
        }

        return {
            setItemGroupField,
            value
        }
    }()
}


export type TDataGroupValueCache = ReturnType<typeof createDataGroupValueCache>


export function createDataGroupValueCache() {

    return function () {
        let dgValue = null as any

        const value = () => dgValue

        function setValue(value: any) {
            dgValue = value
        }

        return {
            setValue,
            value
        }
    }()
}


export function drillStartPosForwardCommon(echartIns: TEchartInstance) {

    const opts = echartIns.getOption() as TEChartOptions

    opts.series.forEach((s, idx) => {
        // s.id = idx.toString()
        // s.universalTransition['seriesKey'] = nextChartOptIds
    })

    // setItemGroup(opts, catDimFieldCache)

    echartIns.setOption(opts, true)
}

export function drillStartPosBackCommon(echartIns: TEchartInstance,
    dataGroupValueCache: TDataGroupValueCache) {

    const opts = echartIns.getOption() as TEChartOptions

    opts.series.forEach((s, idx) => {
        // s.id = idx.toString()
        s.data.forEach(d => {
            if (typeof d === 'object') {
                d['groupId'] = dataGroupValueCache.value
            }
        })
    })

    // setDataGroup(opts, dataGroupValueCache)

    echartIns.setOption(opts, true)
}

export function setItemGroup(options: TEChartOptions, catDimFieldCache: TCatDimFieldCache) {
    // set encode itemGroupID  eq cat dim name
    options.series[0].encode['itemGroupID'] = catDimFieldCache.value()

    // del dataGroupId
    delete options.series[0]['dataGroupId']
}

export function setDataGroup(options: TEChartOptions, dataGroupValueCache: TDataGroupValueCache) {

    options.series.forEach((s, idx) => {
        // s.id = idx.toString()
        // set dataGroupId  eq cat dim name
        s['dataGroupId'] = dataGroupValueCache.value()
        s.data.forEach(d => {
            if (typeof d === 'object') {
                delete d['groupId']
            }
        })
        // del encode itemGroupID
        // delete s.encode['itemGroupID']
    })

}



export function updateFilters(chartInfo: TEChartInfo, actionType: string, paramsValueGetter: (info: TEchartUpdateInfo) => string, model: EChart, infoIndex: number, services: TServices) {

    let valueRecord = null as unknown as string

    chartInfo.updateInfos.forEach(info => {
        if (info.actionType === actionType) {
            valueRecord = paramsValueGetter(info)
        }
    });

    const tableGps = groupBy(chartInfo.updateInfos.filter(v => v.actionType === actionType), v => v.table)
    Object.entries(tableGps).map(([key, rows], index) => {

        const exprs = rows.map(info => {
            valueRecord = paramsValueGetter(info)
            const sqlValue = services.db.parse2sqlValueBaseFieldType(info.table, info.field, valueRecord)

            return `${info.field}=${sqlValue}`
        }).join(' and ')

        addFilterToDataset(exprs, model, infoIndex, services, key);

    })

    return valueRecord
}



export function hasClickInfo(chartInfo: TEChartInfo) {
    return chartInfo.updateInfos.some(info => info.actionType === 'click');
}


export function drillEndPosCommon(options: TEChartOptions, dataGroupValueCache: TDataGroupValueCache) {

    setDataGroup(options, dataGroupValueCache)


}